const toString = Object.prototype.toString;

export function isArray(val: any) {
  return toString.call(val) === '[object Array]';
}

export function isObject(val: any) {
  return val !== null && typeof val === 'object';
}

export function isDate(val: any) {
  return toString.call(val) === '[object Date]';
}

export function isURLSearchParams(val: any) {
  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
}

export function forEach(obj: any, fn: Function) {
  if (obj === null || typeof obj === 'undefined') {
    return;
  }

  if (typeof obj !== 'object') {
    obj = [obj];
  }

  if (isArray(obj)) {
    for (var i = 0, l = obj.length; i < l; i++) {
      fn.call(null, obj[i], i, obj);
    }
  } else {
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fn.call(null, obj[key], key, obj);
      }
    }
  }
}

export function isBoolean(val: any) {
  return typeof val === 'boolean';
}

export function isPlainObject(obj: any) {
  return Object.prototype.toString.call(obj) === '[object Object]';
}

export function deepMerge(obj1: any, obj2: any) {
  let result: any = {};
  function assignValue(val: any, key: any) {
    if (typeof result[key] === 'object' && typeof val === 'object') {
      result[key] = deepMerge(result[key], val);
    } else if (typeof val === 'object') {
      result[key] = deepMerge({}, val);
    } else {
      result[key] = val;
    }
  }
  for (let i = 0, l = arguments.length; i < l; i++) {
    forEach(arguments[i], assignValue);
  }
  return result;
}

export function isUndefined(val: any) {
  return typeof val === 'undefined';
}
